package cn.drenal.capcap.service.impl;

import cn.drenal.capcap.entity.ActivityTag;
import cn.drenal.capcap.entity.ArtworkTag;
import cn.drenal.capcap.entity.Tag;
import cn.drenal.capcap.exception.BizException;
import cn.drenal.capcap.mapper.ActivityTagMapper;
import cn.drenal.capcap.mapper.ArtworkTagMapper;
import cn.drenal.capcap.mapper.TagMapper;
import cn.drenal.capcap.service.TagService;
import cn.drenal.capcap.entity.vo.TagVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 标签服务实现类
 */
@Service
@RequiredArgsConstructor
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements TagService {

    private final ArtworkTagMapper artworkTagMapper;
    private final ActivityTagMapper activityTagMapper;

    @Override
    public TagVO createTag(Tag tag) {
        // 检查标签名称是否已存在
        if (lambdaQuery().eq(Tag::getName, tag.getName()).exists()) {
            throw new BizException("标签名称已存在");
        }
        
        // 设置默认值
        if (tag.getStatus() == null) {
            tag.setStatus(1); // 默认启用
        }
        
        // 保存标签
        save(tag);
        return convertToTagVO(tag);
    }

    @Override
    public TagVO updateTag(Long id, Tag tag) {
        // 检查标签是否存在
        Tag existingTag = getById(id);
        if (existingTag == null) {
            throw new BizException("标签不存在");
        }
        
        // 检查标签名称是否已存在（排除自身）
        if (StringUtils.hasText(tag.getName()) && 
                !tag.getName().equals(existingTag.getName()) && 
                lambdaQuery().eq(Tag::getName, tag.getName()).exists()) {
            throw new BizException("标签名称已存在");
        }
        
        // 更新标签信息
        tag.setId(id);
        updateById(tag);
        
        Tag updatedTag = getById(id);
        return convertToTagVO(updatedTag);
    }

    @Override
    public void deleteTag(Long id) {
        // 检查标签是否存在
        if (!lambdaQuery().eq(Tag::getId, id).exists()) {
            throw new BizException("标签不存在");
        }
        
        // 检查是否有作品使用该标签，如果有则不允许删除
        String tagIdStr = id.toString();
        boolean hasArtworks = !artworkTagMapper.selectList(new LambdaQueryWrapper<ArtworkTag>().eq(ArtworkTag::getTagId, tagIdStr)).isEmpty();
        if (hasArtworks) {
            throw new BizException("该标签已被作品使用，无法删除");
        }
        
        // 检查是否有活动使用该标签，如果有则不允许删除
        boolean hasActivities = !activityTagMapper.selectList(new LambdaQueryWrapper<ActivityTag>().eq(ActivityTag::getTagId, tagIdStr)).isEmpty();
        if (hasActivities) {
            throw new BizException("该标签已被活动使用，无法删除");
        }
        
        // 删除标签
        removeById(id);
    }

    @Override
    public TagVO getTagById(Long id) {
        Tag tag = getById(id);
        if (tag == null) {
            throw new BizException("标签不存在");
        }
        return convertToTagVO(tag);
    }

    @Override
    public Page<TagVO> getTagPage(Page<Tag> page, String name, Integer status) {
        LambdaQueryWrapper<Tag> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        if (StringUtils.hasText(name)) {
            queryWrapper.like(Tag::getName, name);
        }
        
        if (status != null) {
            queryWrapper.eq(Tag::getStatus, status);
        }
        
        // 查询标签列表
        Page<Tag> tagPage = page(page, queryWrapper);
        
        // 转换为TagVO并设置使用次数
        Page<TagVO> tagVOPage = new Page<>(tagPage.getCurrent(), tagPage.getSize(), tagPage.getTotal());
        List<TagVO> tagVOList = tagPage.getRecords().stream()
                .map(this::convertToTagVO)
                .collect(Collectors.toList());
        
        // 按使用次数降序排序
        tagVOList.sort((a, b) -> b.getUseCount().compareTo(a.getUseCount()));
        
        tagVOPage.setRecords(tagVOList);
        return tagVOPage;
    }

    @Override
    public List<TagVO> getAllEnabledTags() {
        List<Tag> tags = lambdaQuery()
                .eq(Tag::getStatus, 1)
                .list();
        
        List<TagVO> tagVOList = tags.stream()
                .map(this::convertToTagVO)
                .collect(Collectors.toList());
        
        // 按使用次数降序排序
        tagVOList.sort((a, b) -> b.getUseCount().compareTo(a.getUseCount()));
        
        return tagVOList;
    }
    
    @Override
    public Long calculateTagUseCount(Long tagId) {
        if (tagId == null) {
            return 0L;
        }
        
        String tagIdStr = tagId.toString();
        
        // 统计作品中使用该标签的次数
        long artworkCount = artworkTagMapper.selectCount(new LambdaQueryWrapper<ArtworkTag>()
                .eq(ArtworkTag::getTagId, tagIdStr));
        
        // 统计活动中使用该标签的次数
        long activityCount = activityTagMapper.selectCount(new LambdaQueryWrapper<ActivityTag>()
                .eq(ActivityTag::getTagId, tagIdStr));
        
        // 返回总使用次数
        return artworkCount + activityCount;
    }
    
    @Override
    public TagVO convertToTagVO(Tag tag) {
        if (tag == null) {
            return null;
        }
        
        TagVO tagVO = TagVO.fromTag(tag);
        
        // 计算并设置使用次数
        Long useCount = calculateTagUseCount(tag.getId());
        tagVO.setUseCount(useCount);
        
        return tagVO;
    }

    @Override
    public List<TagVO> getRandomTags() {
        // 获取所有启用状态的标签
        List<Tag> allTags = lambdaQuery()
                .eq(Tag::getStatus, 1)
                .list();
        
        // 转换为TagVO并按使用次数排序
        List<TagVO> tagVOList = allTags.stream()
                .map(this::convertToTagVO)
                .sorted((a, b) -> b.getUseCount().compareTo(a.getUseCount()))
                .collect(Collectors.toList());
        
        // 返回前10个标签，如果标签总数小于10则返回所有标签
        return tagVOList.stream()
                .limit(10)
                .collect(Collectors.toList());
    }
}